package org.biodas.jdas.client.threads;

import org.apache.log4j.Logger;
import org.biodas.jdas.client.ConnectionPropertyProviderI;

import java.util.Map;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;

/**
 * Created by IntelliJ IDEA.
 * User: ljgarcia
 * Date: 01/12/11
 * Time: 15:41
 * To change this template use File | Settings | File Templates.
 */
public abstract class ClientMultipleSources extends Observable {
    private static Logger logger = Logger.getLogger(ClientMultipleSources.class);
    protected MultipleConnectionPropertyProviderI connProps = null;
    //PoolThread stuff
    protected int poolSize;
    protected int maxPoolSize;
    protected long keepAliveTime;
    protected ThreadPoolExecutorJdas threadPool = null;
    protected final LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();

    public MultipleConnectionPropertyProviderI getConnProps() {
        return this.connProps;
    }
 
    public void setConnProps(MultipleConnectionPropertyProviderI connProps) {
        this.connProps = connProps;
    }

    protected ConnectionPropertyProviderI getConnPropsFor(String source) {
        return this.connProps == null ? null : (ConnectionPropertyProviderI)this.connProps.getConnectionPropertyProviderFor(source);
    }
 
    /**
     * Default constructor, it defines an initial pool with 5 threads, a maximum of 10 threads,
     * and a keepAlive time of 5 seconds.
     */
    protected ClientMultipleSources() {
        this(5, 10, 5, null);
    }

    /**
     * Constructor with parameters, it enables to define the initial pool size, maximum pool size,
     * and keep alive time in seconds; it initializes the ThreadPoolExecutor.
     * @param poolSize Initial pool size
     * @param maxPoolSize Maximum pool size
     * @param keepAliveTime Keep alive time in seconds
     */
    protected ClientMultipleSources(int poolSize, int maxPoolSize, long keepAliveTime) {
        this(poolSize, maxPoolSize, keepAliveTime, null);
    }

    /**
     * Constructor with parameters, it gets an Observer for this object and add it to the observers collection; 
     * it also defines an initial pool with 5 threads, a maximum of 10 threads, and a keepAlive time of 5 seconds.
     * @param observer A new observer for this object
     */
    protected ClientMultipleSources(Observer observer) {
        this(5, 10, 5, observer);
    }

    /**
     * Constructor with parameters, it enables to define the initial pool size, maximum pool size,
     * and keep alive time in seconds; it initializes the ThreadPoolExecutor.
     * @param poolSize Initial pool size
     * @param maxPoolSize Maximum pool size
     * @param keepAliveTime Keep alive time in seconds
     * @param observer A new observer for this object
     */
    protected ClientMultipleSources(int poolSize, int maxPoolSize, long keepAliveTime, Observer observer) {
        this.poolSize = poolSize;
        this.maxPoolSize = maxPoolSize;
        this.keepAliveTime = keepAliveTime;
        this.threadPool = new ThreadPoolExecutorJdas(poolSize, maxPoolSize, keepAliveTime, TimeUnit.SECONDS, queue);
        if (observer != null) {
            this.addObserver(observer);
        }
    }
        /**
        * Run a task with the thread pool and modifies the waiting queue list as needed.
        * @param task
        */
    protected void runTask(Runnable task) {
        threadPool.execute(task);
    }

    /**
     * Shuts down the ThreadPoolExecutor.
     */
    public void shutDown() {
        threadPool.shutdown();
    }

    /**
     * Awaits termination of the ThreadPoolExecutor.
     * Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first.
     * @see java.util.concurrent.ExecutorService
     * @param timeout
     * @param unit
     */
    public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
        return threadPool.awaitTermination(timeout, unit);
    }

    /**
     * Returns true if all tasks have completed following shut down. Note that isTerminated is never true unless either shutdown or shutdownNow was called first
     * @see java.util.concurrent.ExecutorService
     * @return
     */
    public boolean isTerminated() {
         return this.threadPool.isTerminated();
    }

    /**
     * Gets the threadCounting value, it keeps the real size of the execution queue.
     * @return
     */
    public int getThreadCounting() {
        return this.threadPool.getThreadCounting();
    }

    /**
     * Returns true when any thread is still alive, false otherwise.
     * Note that it could be return 1 when the only thread running has already finished but has not been released.
     * @return
     */
    public boolean hasAliveRunners() {
       return this.threadPool.hasAliveRunners();
    }

    /**
     * Sets change status to true and notifies observers.
     * @param arg Object been notified to observers.
     */
    protected void changeAndNotify(Object arg) {
        this.setChanged();
        this.notifyObservers(arg);
    }

    /**
     * Sets change status to true and notifies observers.
     */
    protected void changeAndNotify() {
        this.setChanged();
        this.notifyObservers();
    }
}
